import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.DateFormat;
import java.util.LinkedList;

import org.postgis.PGgeometry;

/**
 * This is a core of map matching processing. Main class of this package will
 * call MapMatcher class to be a coordinate.
 * 
 * */

public class MapMatcher extends Thread {

	private Statement statement_gps_source;
	private Connection conn_mainDB;
	public DateFormat dateFormat;
	private MapMatchAlgo mm;
	private Statement stmtPoint;
	private Statement stmtIn;
	

	public MapMatcher() {
		mm = new MapMatchAlgo();
	}

	public void run() {

		try {

			// establish connections
			Class.forName("org.postgresql.Driver");
			DriverManager.setLoginTimeout(100);

			conn_mainDB = DriverManager.getConnection(MainMap.mainDB, "fang",
					"root");
			statement_gps_source = conn_mainDB.createStatement();
			stmtPoint = conn_mainDB.createStatement();
			stmtIn = conn_mainDB.createStatement();
			ResultSet queryIn = null;
			ResultSet queryPoint = null;

			// create a list of SourceGPS instances
			SourceGPS s = new SourceGPS(conn_mainDB);
			TimePeriodGrouping timePeriod = new TimePeriodGrouping();
			int noDataCnt = 0;

			// get batch
			LinkedList<GPSpnt> pntList = s.getBatch();
			int lSize = pntList.size();

			if (lSize == 0) {
				Util.writeLog(s + " ==> no data to process...");
				noDataCnt++;
			}

			// loop each point
			for (int i = 0; i < lSize; i++) {

				GPSpnt p = pntList.get(i);

				// Transform into the_geom
				int row_id = p.row_id;
				double lat = p.lat;
				double lng = p.lng;

				queryPoint = stmtPoint
						.executeQuery("SELECT ST_PointFromText('POINT(" + lng
								+ " " + lat + ")') AS the_geom");
				queryPoint.next();
				PGgeometry geom = (PGgeometry) queryPoint.getObject("the_geom");
				String Query = String
						.format("select ST_within((select st_astext('"
								+ geom
								+ "') from \"%s\".\"%s\" where row_id = "
								+ row_id
								+ "),(select st_astext(latlong) from \"%s\".\"%s\" where id = 2))",
								Config.SCHEMA_NAME_GPS_DATA,
								Config.TABLE_NAME_GPS_DATA,
								Config.SCHEMA_NAME_POLYGON_DATA,
								Config.TABLE_NAME_POLYGON_DATA);
				queryIn = stmtIn.executeQuery(Query);
				queryIn.next();
				boolean status = queryIn.getBoolean(1);

				if (status == true) {
					// run Map Matching Algorithm
					MapMatchResult mmResult = mm.mapmatch(p);
					// First, the pattern of dateTime without timezone is
					// "MM/DD/YYYY HH:MM:SS"
					String[] dateTimeStr = Util
							.splitWithSpace2A(pntList.get(i).rectimeStr);

					// Get date MM/DD/YYYY
					String dateStr = dateTimeStr[0].toString();
					// System.out.println(mmResult);

					// If the linkID is found, the linkID will be updated to a
					// current record.
					if (mmResult.linkID > -1) {
						// identify the day of date,i.e.,Mon., Tues.
						String dayName = timePeriod.identifyDaysOfWeek(dateStr);
						String insertQuery = String.format(
								"UPDATE \"%s\".\"%s\" SET "
										+ "\"dayName\" = \'"
										+ dayName.toLowerCase()
										+ "\' ,\"linkID\" = " + mmResult.linkID
										+ ",\"lamda\"= " + mmResult.lambda
										+ " WHERE row_id = " + row_id,
								Config.SCHEMA_NAME_GPS_DATA,
								Config.TABLE_NAME_GPS_DATA);
						//System.out.println(row_id);
						statement_gps_source.executeUpdate(insertQuery);
					}
				}
			}

			// release resources
			pntList.clear();

		} catch (Exception e) {
			e.printStackTrace();
			System.exit(1);
		} finally {
			// close connections
			try {
				conn_mainDB.close();
				statement_gps_source.close();
			} catch (SQLException e) {
				System.exit(1);
			}
		}
	}
}
